package com.lingjtx.common.pay.handle;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.lingjtx.common.core.algorithm.AESUtil;
import com.lingjtx.common.core.algorithm.RSAUtil;
import com.lingjtx.common.core.constant.Const;
import com.lingjtx.common.core.util.DateTimeUtil;
import com.lingjtx.common.core.util.StringUtil;
import com.lingjtx.common.pay.callback.NotifyType;
import com.lingjtx.common.pay.client.PaymentExecutor;
import com.lingjtx.common.pay.model.NotifyEntity;
import com.lingjtx.common.pay.model.OrderEntity;
import com.lingjtx.common.pay.model.RefundEntity;
import com.lingjtx.common.pay.model.wx.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.UUID;

@Service("wePayService")
public class WePayService implements PayHandler {

    private static final Logger log = LoggerFactory.getLogger(WePayService.class);

    private final PaymentExecutor executor;

    public WePayService(PaymentExecutor executor) {
        this.executor = executor;
    }

    @Override
    public String nativeOrder(OrderEntity model) {
        WinXinPrepayResponse response = executor.wxPayNative(model);
        return response.getCode_url();
    }

    @Override
    public Object appOrder(OrderEntity model) {
        WinXinPrepayResponse response = executor.wxPayApp(model);
        String nonceStr = UUID.randomUUID().toString();
        String timestamp = DateTimeUtil.getTimestampBySecond();

        String text = executor.getProperties().getAppid() + "\n" +
                timestamp + "\n" +
                nonceStr + "\n" +
                response.getPrepay_id() + "\n";

        String sign = RSAUtil.sign(text, executor.getProperties().getPriKey());

        WxAppOrderVo appOrderVo = new WxAppOrderVo();
        appOrderVo.setAppid(executor.getProperties().getAppid());
        appOrderVo.setPartnerid(executor.getProperties().getMchid());
        appOrderVo.setOrderNo(model.getOrderNo());
        appOrderVo.setPrepayId(response.getPrepay_id());
        appOrderVo.setNoncestr(nonceStr);
        appOrderVo.setTimestamp(timestamp);
        appOrderVo.setSign(sign);
        return appOrderVo;
    }

    @Override
    public Object miniProgramOrder(OrderEntity model) {
        WinXinPrepayResponse response = executor.wxPayJsapi(model);
        String nonceStr = UUID.randomUUID().toString();
        String timestamp = DateTimeUtil.getTimestampBySecond();

        WxJsapiOrderVo jsapiOrderVo = new WxJsapiOrderVo();
        jsapiOrderVo.setAppId(executor.getProperties().getMiniAppid());
        jsapiOrderVo.setOrderNo(model.getOrderNo());
        jsapiOrderVo.setPackage("prepay_id=" + response.getPrepay_id());
        jsapiOrderVo.setNonceStr(nonceStr);
        jsapiOrderVo.setTimeStamp(timestamp);

        String text = jsapiOrderVo.getAppId() + "\n" +
                timestamp + "\n" +
                nonceStr + "\n" +
                jsapiOrderVo.getPackage() + "\n";

        String sign = RSAUtil.sign(text, executor.getProperties().getPriKey());

        jsapiOrderVo.setPaySign(sign);
        return jsapiOrderVo;
    }

    @Override
    public String h5Order(OrderEntity model) {
        WinXinPrepayResponse response = executor.wxPayH5(model);
        if (StringUtil.isNotEmpty(response.getH5_url())) {
            return response.getH5_url() + "&redirect_url=" + URLEncoder.encode(Const.WEBURL, StandardCharsets.UTF_8);
        }
        return "H5 支付未开通服务，请在微信商户平台开通";
    }

    @Override
    public Object getOrderDetail(String orderNo) {
        return executor.wxQueryOrderDetail(orderNo);
    }

    @Override
    public Object refunds(RefundEntity model) {
        AmountEntity amount = new AmountEntity();
        amount.setRefund(model.getRefund());
        amount.setTotal(model.getTotal());

        return executor.wxRefunds(model.getOrderNo(), model.getNotifyUrl(), amount);
    }

    @Override
    public void closeOrder(String orderNo) {
        JSONObject response = executor.wxCloseOrder(orderNo);
        log.info("微信支付已关闭订单: {}", response.toString());
    }

    @Override
    public NotifyEntity handle(String data) {
        NotifyEntity notify = new NotifyEntity();
        PaymentNotify paymentNotify = JSON.parseObject(data, PaymentNotify.class);
        notify.setId(paymentNotify.getId());
        notify.setCreateTime(paymentNotify.getCreate_time());
        notify.setSummary(paymentNotify.getSummary());
        if ("TRANSACTION.SUCCESS".equals(paymentNotify.getEvent_type())) {
            notify.setSuccess(true);
        }

        ResourceNotify resource = paymentNotify.getResource();
        String text = AESUtil.decryptToString(resource.getCiphertext(),
                executor.getProperties().getApiKey(),
                resource.getAssociated_data(),
                resource.getNonce());
        notify.setData(text);
        notify.setNotifyType(NotifyType.of(resource.getOriginal_type()));
        return notify;
    }
}
